import type { StixMalwareAnalysis, StoreEntityMalwareAnalysis } from './malwareAnalysis-types';
import {
  ATTRIBUTE_ANALYSIS_SCO,
  ATTRIBUTE_HOST_VM,
  ATTRIBUTE_INSTALLED_SOFTWARE,
  ATTRIBUTE_OPERATING_SYSTEM,
  ATTRIBUTE_SAMPLE,
  ENTITY_TYPE_MALWARE_ANALYSIS,
  INPUT_ANALYSIS_SCO,
  INPUT_HOST_VM,
  INPUT_INSTALLED_SOFTWARE,
  INPUT_OPERATING_SYSTEM,
  INPUT_SAMPLE,
  RELATION_ANALYSIS_SCO,
  RELATION_HOST_VM,
  RELATION_INSTALLED_SOFTWARE,
  RELATION_OPERATING_SYSTEM,
  RELATION_SAMPLE
} from './malwareAnalysis-types';
import { ABSTRACT_STIX_CYBER_OBSERVABLE, ABSTRACT_STIX_DOMAIN_OBJECT } from '../../schema/general';
import { RELATION_ANALYSIS_OF, RELATION_CHARACTERIZES, RELATION_DYNAMIC_ANALYSIS_OF, RELATION_STATIC_ANALYSIS_OF } from '../../schema/stixCoreRelationship';
import { ENTITY_TYPE_MALWARE } from '../../schema/stixDomainObject';
import { REL_BUILT_IN } from '../../database/stix';
import type { ModuleDefinition } from '../../schema/module';
import { registerDefinition } from '../../schema/module';

import convertMalwareAnalysisToStix from './malwareAnalysis-converter';
import {
  ENTITY_DOMAIN_NAME,
  ENTITY_HASHED_OBSERVABLE_ARTIFACT,
  ENTITY_HASHED_OBSERVABLE_STIX_FILE,
  ENTITY_HOSTNAME,
  ENTITY_NETWORK_TRAFFIC,
  ENTITY_SOFTWARE,
  ENTITY_URL,
  isStixCyberObservable
} from '../../schema/stixCyberObservable';
import { objectAssignee, objectOrganization } from '../../schema/stixRefRelationship';

export const MALWARE_ANALYSIS_DEFINITION: ModuleDefinition<StoreEntityMalwareAnalysis, StixMalwareAnalysis> = {
  type: {
    id: 'malwareAnalyses',
    name: ENTITY_TYPE_MALWARE_ANALYSIS,
    category: ABSTRACT_STIX_DOMAIN_OBJECT,
    aliased: false
  },
  identifier: {
    definition: {
      [ENTITY_TYPE_MALWARE_ANALYSIS]: [{ src: 'product' }, { src: 'result_name' }, { src: 'submitted' }]
    },
    resolvers: {}
  },
  overviewLayoutCustomization: [
    { key: 'details', width: 6, label: 'Entity details' },
    { key: 'basicInformation', width: 6, label: 'Basic information' },
    { key: 'latestCreatedRelationships', width: 6, label: 'Latest created relationships' },
    { key: 'latestContainers', width: 6, label: 'Latest containers' },
    { key: 'externalReferences', width: 6, label: 'External references' },
    { key: 'mostRecentHistory', width: 6, label: 'Most recent history' },
    { key: 'notes', width: 12, label: 'Notes about this entity' },
  ],
  attributes: [
    { name: 'product', label: 'Product', type: 'string', format: 'short', mandatoryType: 'external', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'version', label: 'Product version', type: 'string', format: 'short', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'configuration_version', label: 'Configuration version', type: 'string', format: 'short', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'modules', label: 'Modules', type: 'string', format: 'short', mandatoryType: 'customizable', editDefault: true, multiple: true, upsert: true, isFilterable: true },
    { name: 'analysis_engine_version', label: 'Analysis engine version', type: 'string', format: 'short', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'analysis_definition_version', label: 'Analysis definition version', mandatoryType: 'customizable', editDefault: true, type: 'string', format: 'short', multiple: false, upsert: true, isFilterable: true },
    { name: 'submitted', label: 'Submission date', type: 'date', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'analysis_started', label: 'Analysis start date', type: 'date', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'analysis_ended', label: 'Analysis end date', type: 'date', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
    { name: 'result_name', label: 'Result name', type: 'string', format: 'short', mandatoryType: 'external', editDefault: true, multiple: false, upsert: true, isFilterable: false },
    { name: 'result', label: 'Maliciousness', type: 'string', format: 'vocabulary', vocabularyCategory: 'malware_result_ov', mandatoryType: 'customizable', editDefault: true, multiple: false, upsert: true, isFilterable: true },
  ],
  converter: convertMalwareAnalysisToStix,
  representative: (stix: StixMalwareAnalysis) => {
    return `${stix.product} - ${stix.result_name}`;
  },
  relations: [
    {
      name: RELATION_CHARACTERIZES,
      targets: [
        { name: ENTITY_TYPE_MALWARE, type: REL_BUILT_IN },
      ]
    },
    {
      name: RELATION_ANALYSIS_OF,
      targets: [
        { name: ENTITY_TYPE_MALWARE, type: REL_BUILT_IN },
      ]
    },
    {
      name: RELATION_STATIC_ANALYSIS_OF,
      targets: [
        { name: ENTITY_TYPE_MALWARE, type: REL_BUILT_IN },
      ]
    },
    {
      name: RELATION_DYNAMIC_ANALYSIS_OF,
      targets: [
        { name: ENTITY_TYPE_MALWARE, type: REL_BUILT_IN },
      ]
    },
  ],
  relationsRefs: [
    objectOrganization,
    { ...objectAssignee, isFilterable: false },
    {
      name: INPUT_HOST_VM,
      type: 'ref',
      databaseName: RELATION_HOST_VM,
      stixName: ATTRIBUTE_HOST_VM,
      mandatoryType: 'no',
      editDefault: false,
      multiple: false,
      upsert: true,
      datable: true,
      isRefExistingForTypes(this, _, toType) {
        return this.toTypes.includes(toType);
      },
      label: 'VM Host',
      isFilterable: true,
      toTypes: [ENTITY_SOFTWARE],
    },
    {
      name: INPUT_OPERATING_SYSTEM,
      type: 'ref',
      databaseName: RELATION_OPERATING_SYSTEM,
      stixName: ATTRIBUTE_OPERATING_SYSTEM,
      mandatoryType: 'no',
      editDefault: false,
      multiple: false,
      upsert: true,
      datable: true,
      label: 'Malware analysis operating System',
      isRefExistingForTypes(this, _, toType) {
        return this.toTypes.includes(toType);
      },
      isFilterable: true,
      toTypes: [ENTITY_SOFTWARE],
    },
    {
      name: INPUT_INSTALLED_SOFTWARE,
      type: 'ref',
      databaseName: RELATION_INSTALLED_SOFTWARE,
      stixName: ATTRIBUTE_INSTALLED_SOFTWARE,
      mandatoryType: 'no',
      editDefault: false,
      multiple: true,
      upsert: true,
      datable: true,
      label: 'Installed software',
      isRefExistingForTypes(this, _, toType) {
        return this.toTypes.includes(toType);
      },
      isFilterable: true,
      toTypes: [ENTITY_SOFTWARE],
    },
    {
      name: INPUT_ANALYSIS_SCO,
      type: 'ref',
      databaseName: RELATION_ANALYSIS_SCO,
      stixName: ATTRIBUTE_ANALYSIS_SCO,
      mandatoryType: 'no',
      editDefault: false,
      multiple: true,
      upsert: true,
      datable: true,
      label: 'Analysis SCO',
      isRefExistingForTypes(this, _, toType) {
        return isStixCyberObservable(toType);
      },
      isFilterable: true,
      toTypes: [ABSTRACT_STIX_CYBER_OBSERVABLE],
    },
    {
      name: INPUT_SAMPLE,
      type: 'ref',
      databaseName: RELATION_SAMPLE,
      stixName: ATTRIBUTE_SAMPLE,
      mandatoryType: 'no',
      editDefault: false,
      multiple: false,
      upsert: true,
      datable: true,
      isRefExistingForTypes(this, _, toType) {
        return this.toTypes.includes(toType);
      },
      toTypes: [
        ENTITY_HASHED_OBSERVABLE_ARTIFACT,
        ENTITY_HASHED_OBSERVABLE_STIX_FILE,
        ENTITY_NETWORK_TRAFFIC,
        ENTITY_DOMAIN_NAME,
        ENTITY_URL,
        ENTITY_HOSTNAME
      ],
      label: 'Malware analysis sample',
      isFilterable: true,
    }
  ]

};

registerDefinition(MALWARE_ANALYSIS_DEFINITION);
